抽象类
概述
在面向对象编程中,抽象类是一种特殊的类,它不能被实例化,只能被继承。抽象类通常用于定义一组子类的共同行为和属性,但它们本身并不完整,需要子类来实现具体的功能。抽象类可以包含抽象方法,这些方法在抽象类中只有声明而没有实现,具体的实现由子类提供。
为什么使用抽象类?
抽象类的主要用途是提供一个通用的接口或模板,确保所有子类都实现某些特定的方法。这有助于代码的组织和维护,尤其是在处理复杂的继承层次结构时。
抽象类的定义
在 TypeScript 中,抽象类通过 abstract 关键字来定义。抽象类可以包含抽象方法和具体方法。
语法
abstract class AbstractClass {
abstract abstractMethod(): void; // 抽象方法
concreteMethod(): void { // 具体方法
console.log("This is a concrete method.");
}
}
抽象方法
抽象方法在抽象类中只有声明,没有实现。子类必须实现这些抽象方法。
abstract class Animal {
abstract makeSound(): void; // 抽象方法
move(): void { // 具体方法
console.log("Moving...");
}
}
具体方法
具体方法在抽象类中有完整的实现,子类可以选择性地覆盖这些方法。
abstract class Animal {
abstract makeSound(): void; // 抽象方法
move(): void { // 具体方法
console.log("Moving...");
}
}
继承抽象类
子类继承抽象类时,必须实现所有的抽象方法。如果子类没有实现抽象方法,编译器会报错。
class Dog extends Animal {
makeSound(): void {
console.log("Woof!");
}
}
class Cat extends Animal {
makeSound(): void {
console.log("Meow!");
}
}
实例化
抽象类不能被实例化,只能通过子类来实例化。
// 错误示例:不能直接实例化抽象类
// const animal = new Animal(); // 编译错误
// 正确示例:通过子类实例化
const dog = new Dog();
dog.makeSound(); // 输出: Woof!
dog.move(); // 输出: Moving...
const cat = new Cat();
cat.makeSound(); // 输出: Meow!
cat.move(); // 输出: Moving...
实践练习
练习 1:定义一个抽象类 Shape
定义一个抽象类 Shape,包含一个抽象方法 calculateArea() 和一个具体方法 display()。然后创建两个子类 Circle 和 Rectangle,分别实现 calculateArea() 方法。
abstract class Shape {
abstract calculateArea(): number;
display(): void {
console.log(`Area: ${this.calculateArea()}`);
}
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
calculateArea(): number {
return Math.PI * this.radius ** 2;
}
}
class Rectangle extends Shape {
constructor(private width: number, private height: number) {
super();
}
calculateArea(): number {
return this.width * this.height;
}
}
const circle = new Circle(5);
circle.display(); // 输出: Area: 78.53981633974483
const rectangle = new Rectangle(4, 6);
rectangle.display(); // 输出: Area: 24
练习 2:定义一个抽象类 Employee
定义一个抽象类 Employee,包含一个抽象方法 calculateSalary() 和一个具体方法 displayInfo()。然后创建两个子类 FullTimeEmployee 和 PartTimeEmployee,分别实现 calculateSalary() 方法。
abstract class Employee {
constructor(protected name: string, protected id: number) {}
abstract calculateSalary(): number;
displayInfo(): void {
console.log(`Name: ${this.name}, ID: ${this.id}, Salary: ${this.calculateSalary()}`);
}
}
class FullTimeEmployee extends Employee {
constructor(name: string, id: number, private monthlySalary: number) {
super(name, id);
}
calculateSalary(): number {
return this.monthlySalary;
}
}
class PartTimeEmployee extends Employee {
constructor(name: string, id: number, private hourlyRate: number, private hoursWorked: number) {
super(name, id);
}
calculateSalary(): number {
return this.hourlyRate * this.hoursWorked;
}
}
const fullTimeEmployee = new FullTimeEmployee("John Doe", 1, 5000);
fullTimeEmployee.displayInfo(); // 输出: Name: John Doe, ID: 1, Salary: 5000
const partTimeEmployee = new PartTimeEmployee("Jane Smith", 2, 20, 100);
partTimeEmployee.displayInfo(); // 输出: Name: Jane Smith, ID: 2, Salary: 2000
总结
抽象类是面向对象编程中的一个重要概念,它提供了一种机制来定义通用的接口和模板,确保子类实现特定的方法。通过抽象类,我们可以更好地组织和维护代码,尤其是在处理复杂的继承层次结构时。希望本教程能帮助你理解抽象类的概念和使用方法,并通过实践练习加深理解。